package cuppics;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.junit.Test;

public class Prj22 {

	/**
	 * Using names.txt (right click and 'Save Link/Target As...'), a 46K text
	 * file containing over five-thousand first names, begin by sorting it into
	 * alphabetical order. Then working out the alphabetical value for each
	 * name, multiply this value by its alphabetical position in the list to
	 * obtain a name score.
	 * 
	 * For example, when the list is sorted into alphabetical order, COLIN,
	 * which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list.
	 * So, COLIN would obtain a score of 938 × 53 = 49714.
	 * 
	 * What is the total of all the name scores in the file?
	 */
	@Test
	public void test() {

		System.out.println(Calculator.calculate());
	}

	public static class Calculator {

		public static final String PATH = "D:\\workSpace\\java\\cuppics\\src\\test\\java\\cuppics\\Prj22_data.txt";

		public static int calculate() {
			try {
				List<String> dataStrList = readNameStrs(PATH);

				BinaryTree<String> bt = new BinaryTree<String>();
				
				for (int i = 0; i < dataStrList.size(); i++) {
					bt.insert(dataStrList.get(i));
				}
				
				List<String> orderStrs = bt.inOrder();
				int sum = 0;
				for( int i = 0 ; i < orderStrs.size(); i ++){
					sum += (i + 1) * calculateStrVal(orderStrs.get(i));
				}
				
				return sum;

			} catch (IOException e) {
				e.printStackTrace();
			}
			return 0; 
		}

		private static int calculateStrVal(String str) {
			
			char[] charArr = new char[ str.length()];
			str.getChars(0,  charArr.length, charArr, 0);
			
			int sum = 0;
			for( int i = 0 ; i < charArr.length; i ++){
				sum += (int)(charArr[i] - 'A') + 1;
			}
			return sum;
		}

		private static List<String> readNameStrs(String path)
				throws IOException {

			StringBuffer sb = new StringBuffer();

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					new FileInputStream(new File(path))));
			String str = "";
			while ((str = reader.readLine()) != null) {
				sb.append(str);
			}

			reader.close();

			String[] strArrs = sb.toString().split(",");

			List<String> arrs = new ArrayList<String>();

			for (int i = 0; i < strArrs.length; i++) {
				String tp = StrUtils.removeChar('"', strArrs[i]);

				arrs.add(tp);
			}

			return arrs;
		}

	}

	public static class StrUtils {

		public static String removeChar(char specialStr, String str) {
			char[] charArr = new char[str.length()];
			char[] tp = new char[str.length()];

			str.getChars(0, charArr.length, charArr, 0);

			int j = 0;
			for (int i = 0; i < charArr.length; i++) {
				if (charArr[i] == specialStr) {

				} else {
					tp[j++] = charArr[i];
				}
			}

			return new String(tp, 0, j);
		}

	}

	/************************ binary tree *******************************************/

	public static class BinaryTree<T extends Comparable<T>> {

		private Node<T> root;

		public void insert(T e) {
			if (e == null) {
				throw new IllegalArgumentException("can't be null!!!");
			}

			if (root == null) {
				root = new Node<T>(null, e);
			} else {
				Node<T> current = root;
				Node<T> parent;

				while (true) {
					parent = current;
					if (e.compareTo(parent.getData()) == 0) {
						throw new IllegalArgumentException(" already exist "
								+ e.toString());
					} else if (e.compareTo(parent.getData()) < 0) {
						current = current.leftChild;
						if (current == null) {
							Node<T> newNode = new Node<T>(parent, e);
							parent.leftChild = newNode;
							return;
						}

					} else {
						current = current.rightChild;
						if (current == null) {
							Node<T> newNode = new Node<T>(parent, e);
							parent.rightChild = newNode;
							return;
						}
					}
				}
			}
		}

		public List<T> inOrder() {
			List<T> list = new LinkedList<T>();
			inOrderTraverse(root.leftChild, list);
			list.add(root.data);
			inOrderTraverse(root.rightChild, list);

			return list;
		}

		private void inOrderTraverse(Node<T> node, List<T> list) {

			if (node != null) {
				inOrderTraverse(node.leftChild, list);
				list.add(node.data);
				inOrderTraverse(node.rightChild, list);
			}
		}

		@SuppressWarnings("hiding")
		class Node<T> {
			private Node<T> parent;
			private Node<T> leftChild;
			private Node<T> rightChild;

			private T data;

			public Node(Node<T> parent, T data) {
				this.parent = parent;
				this.data = data;
			}

			/**
			 * @return the parent
			 */
			public Node<T> getParent() {
				return parent;
			}

			/**
			 * @return the leftChild
			 */
			public Node<T> getLeftChild() {
				return leftChild;
			}

			/**
			 * @return the rightChild
			 */
			public Node<T> getRightChild() {
				return rightChild;
			}

			/**
			 * @return the data
			 */
			public T getData() {
				return data;
			}

			/**
			 * @param parent
			 *            the parent to set
			 */
			public void setParent(Node<T> parent) {
				this.parent = parent;
			}

			/**
			 * @param leftChild
			 *            the leftChild to set
			 */
			public void setLeftChild(Node<T> leftChild) {
				this.leftChild = leftChild;
			}

			/**
			 * @param rightChild
			 *            the rightChild to set
			 */
			public void setRightChild(Node<T> rightChild) {
				this.rightChild = rightChild;
			}

			/**
			 * @param data
			 *            the data to set
			 */
			public void setData(T data) {
				this.data = data;
			}

		}

	}
}
